/**
 *  @file SSLCallbacks.cpp
 */

#include "SSLCallbacks.h"
#include "../../convert/Convert.h"

namespace cppflib
{

namespace net
{

namespace ssl
{

/**
 *  Test whether a host name matches a pattern
 *
 *  @note host names are case-insensitive
 *
 *  @param[in] targetHostName -- host name to be checked
 *  @param[in] hostNamePattern -- may be a pattern (e.g. *.google.com) or a normal host name (e.g. www.google.com)
 *                                but *CANNOT* contain double wildcard (e.g. *.*.abc.com)
 *
 *  @return true if hostname matches the pre-set targetHostName
 */
_DLLAPI bool IsHostNameMatched(const CFString & targetHostName, const CFString & hostNamePattern)
{
   int srcIndex = 0, patternIndex = 0;
   while (srcIndex < targetHostName.GetLength() && 
          patternIndex < hostNamePattern.GetLength()) {

      wc_t sc = targetHostName[srcIndex++];
      wc_t tc = hostNamePattern[patternIndex++];

      if (tc == _S('*')) {
         if (patternIndex >= hostNamePattern.GetLength())  // '*' at the end matches anything
            return true;

         --srcIndex;
         pcwstr_t pPattern = static_cast<pcwstr_t>(hostNamePattern);
         int pos = targetHostName.FindNoCase(&pPattern[patternIndex], srcIndex);
         if (pos < 0)
            break;
            
         srcIndex = pos; // start comparing again from where the pattern matched
         continue;
      }

      if (convert::ToWUpper(sc) != convert::ToWUpper(tc))
         break;
   }

   // matched if both can reach the end
   return (srcIndex >= targetHostName.GetLength() && patternIndex >= hostNamePattern.GetLength());
}


} // end of namespace ssl

} // end of namespace net

} // end of namespace cppflib
